<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
  <title>KML Interactive Sampler</title>
  <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
  <script type="text/javascript" src="https://www.google.com/jsapi?autoload=%7B%22modules%22%3A%5B%7B%22name%22%3A%22maps%22%2C%22version%22%3A%222%22%7D%2C%7B%22name%22%3A%22earth%22%2C%22version%22%3A%221%22%7D%5D%7D%0A&key=ABQIAAAAKkfkHb2nXsD0o1OX2TbdkRRaozj48i9kKhnMmF3N7B7M7uPI0BRRfUKwr6fFsCZXrI626zu0YJBiPQ"></script>
  <script type="text/javascript" src="https://earth-api-utility-library.googlecode.com/svn/tags/extensions-0.2.1/dist/extensions.pack.js"></script>
  <script type="text/javascript" src="kml-ref.js"></script>
  <script type="text/javascript" src="lib/base64.js"></script>
  <script type="text/javascript" src="lib/codemirror/js/codemirror.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/dojo/1.6.2/dojo/dojo.xd.js"></script>
  <style type="text/css">
    @import "https://ajax.googleapis.com/ajax/libs/dojo/1.2.3/dijit/themes/nihilo/nihilo.css";
    @import "https://ajax.googleapis.com/ajax/libs/dojo/1.2.3/dojo/resources/dojo.css";
  </style>

  <style type="text/css">@import "index.css";</style>
<script type="text/javascript">
/* <![CDATA[ */

var g_ge;
var g_gex;
var g_editor;
var g_editorReady = false;
var g_earthDisabled = false;
var g_editorDirty = false;
var g_kmlObject;
var g_infoBoxVisible = true;
var g_startNode = null;
var aspectRatio;

google.setOnLoadCallback(function() {
  dojo.require('dijit.layout.BorderContainer');
  dojo.require('dijit.layout.ContentPane');
  dojo.require('dojo.data.ItemFileReadStore');
  dojo.require('dijit.Tree');
  dojo.require('dijit.form.Button');
  dojo.require('dojo.parser');
  dojo.require('dojo.cookie');
  dojo.require('dojo.fx');

  dojo.addOnLoad(function() {
    // http://www.alexatnet.com/node/69
    dojo.declare(
      "AutoExpandRootTree",
      dijit.Tree,
    {
      _createTreeNode: function()
      {
        var node = dijit.Tree.prototype._createTreeNode.apply(this, arguments);
        var itemIdentity = this.model.getIdentity(node.item);
        if (itemIdentity) {
          // expand sections
          if (itemIdentity.match(/^section:/)) {
            this._expandNode(node);
          }

          // expand parents of the sample anchor, and select the sample anchor
          var anchor = document.location.hash.substr(1); // drop hash character
          if (anchor && anchor.substr(0, itemIdentity.length) == itemIdentity) {
            this._expandNode(node);

            if (anchor == itemIdentity) {
              g_startNode = node;
            }
          }
        }

        return node;
      }
    });

    if (dojo.cookie('width-left')) {
      dojo.byId('left').style.width = dojo.cookie('width-left');
    }

    if (dojo.cookie('width-right')) {
      dojo.byId('right').style.width = dojo.cookie('width-right');
    }

    dojo.parser.parse();
    dojo.byId('loading').style.display = 'none';
    dojo.byId('container').style.visibility = 'visible';

    // build earth
    google.earth.createInstance(
      'map3d',
      function(ge) {
        g_ge = ge;
        g_ge.getWindow().setVisibility(true);

        g_ge.getNavigationControl().setVisibility(ge.VISIBILITY_AUTO);
        g_ge.getLayerRoot().enableLayerById(g_ge.LAYER_BORDERS, true);
        g_ge.getLayerRoot().enableLayerById(g_ge.LAYER_BUILDINGS, true);

        g_gex = new GEarthExtensions(g_ge);

        tryOpenStartNode();
      },
      function() {
        g_earthDisabled = true;
        dijit.byId('update-button').setDisabled(true);
      });

    // create code editor
    g_editor = CodeMirror.fromTextArea('editor', {
      parserfile: 'parsexml.js',
      stylesheet: 'xmlcolors.css',
      path: 'lib/codemirror/js/',
      textWrapping: false,
      continuousScanning: 500,
      lineNumbers: true,
      tabMode: 'shift',
      initCallback: function(obj) {
        //obj.setCode('test');
        updateUsefulLinks();

        g_editorReady = true;
        tryOpenStartNode();
      },
      saveFunction: function() {
        reloadKml();
      },
      onChange: onEditorChanged
    });

    // enable or disable download button based on browser's support for data urls
    if (!dataUrlsSupported()) {
      dijit.byId('download-button').setDisabled(true);
      dijit.byId('download-button').setAttribute('title', 'Requires Firefox 3+ or Safari 3.2+');
    }

    // watch splitter resize and set layout cookies
    dojo.connect(dijit.byId('container').getSplitter('left'), '_stopDrag', null, function() {
      dojo.cookie('width-left', dojo.byId('left').style.width);
    });

    dojo.connect(dijit.byId('container').getSplitter('right'), '_stopDrag', null, function() {
      dojo.cookie('width-right', dojo.byId('right').style.width);
    });

    // show or hide infobox
    if (dojo.cookie('show-info-box') == 'false') {
      g_infoBoxVisible = false;
      dojo.style('info-box', 'display', 'none');
      dojo.addClass('info-box-toggle', 'off');
      //dijit.byId('info-box').layout();
      dijit.byId('center').layout();
    }

    window.onbeforeunload = function() {
      if (g_editorDirty) {
        return "You've made changes to the KML. Press OK if you're sure " +
               "you want to exit.";
      }
    };

    tryOpenStartNode();
  });
});

function tryOpenStartNode() {
  if (!g_editorReady || !g_ge)
    return;

  // load start node if its defined
  if (g_startNode) {
    // faux select
    var tree = dijit.byId('tree');
    tree._publish("execute", { item: g_startNode.item, node: g_startNode} );
    tree.onClick(g_startNode.item, g_startNode);
    tree.focusNode(g_startNode);

    g_startNode = null;
  }
}

var g_editorChangedTimeout = null;
function onEditorChanged() {
  g_editorDirty = true;
  if (g_editorChangedTimeout) {
    clearTimeout(g_editorChangedTimeout);
    g_editorChangedTimeout = null;
  }

  g_editorChangedTimeout = setTimeout(updateUsefulLinks, 500);
}

function updateUsefulLinks() {
  var re = /<([^\s]+?)(\s.*?)?>/;
  var code = g_editor.getCode();

  var usedTags = {};
  while ((m = re.exec(code)) !== null) {
    usedTags[m[1]] = true;
    code = code.substr(m[0].length);
  }

  var usedTagsArr = [];
  for (var tag in usedTags)
    usedTagsArr.push(tag);

  var linksHtml = '';
  var first = true;

  usedTagsArr.sort(function(a,b){ return (a.toLowerCase() < b.toLowerCase()) ? -1 : 1; });
  for (var i = 0; i < usedTagsArr.length; i++) {
    var tag = usedTagsArr[i];
    var tagRef = getTagKmlRef(tag);
    if (!tagRef)
      continue;

    if (!first)
      linksHtml += ', ';

    linksHtml += '<a href="' + tagRef.refLink + '" target="_blank">&lt;' + tagRef.tag + '&gt;</a>';
    first = false;
  }

  dojo.query('#useful-links div')[0].innerHTML = linksHtml;

  dijit.byId('center').layout();
}

function loadSample(path, descPath) {
  if (g_editorDirty) {
    if (!confirm("You've made changes to the KML. Press OK if you're sure " +
                 "you want to load a new sample."))
      return false;
  }

  g_editorDirty = false;
  var editIframe = dojo.query('iframe', 'center');
  editIframe.style('position', 'absolute');
  dojo.style('editor-loading', 'display', 'block');

  var sampleInstructions = dijit.byId('sample-instructions');
  if (descPath) {
    google.maps.DownloadUrl('../morekml/' + descPath, function(data, httpResponseCode) {
      if (data && httpResponseCode == 200) {
        sampleInstructions.setContent(data);
      } else {
        sampleInstructions.setContent('Error: <em>Cannot load description.</em>');
      }

      //dijit.byId('info-box').layout();
      dijit.byId('center').layout();
    });
  } else {
    sampleInstructions.setContent('<em>No instructions provided.</em>');
    //dijit.byId('info-box').layout();
    dijit.byId('center').layout();
  }

  google.maps.DownloadUrl('../morekml/' + path, function(data, httpResponseCode) {
    if (data && httpResponseCode == 200) {
      g_editor.setCode(data);
      updateUsefulLinks();
      if (!g_earthDisabled)
        reloadKml(data);

      dojo.style('editor-loading', 'display', 'none');
      editIframe.style('position', 'static');
      editIframe.style('left', '0');
    } else {
      alert('Error loading KML: HTTP ' + httpResponseCode.toString());
    }
  });
}

function reloadKml(kmlString) {
  if (!kmlString)
    kmlString = g_editor.getCode();

  g_ge.setBalloon(null);

  if (g_kmlObject)
    g_ge.getFeatures().removeChild(g_kmlObject);

  var tourFound = false;

  try {
    g_kmlObject = g_ge.parseKml(kmlString);

    // see if we should show sky
    // TODO: better parsing!
    if (kmlString.indexOf('target=sky') >= 0)
      g_ge.getOptions().setMapType(g_ge.MAP_TYPE_SKY);
    else
      g_ge.getOptions().setMapType(g_ge.MAP_TYPE_EARTH);

    //reparse g_kmlObject which gets corrupted after setMapType
    g_kmlObject = g_ge.parseKml(kmlString);
    g_ge.getFeatures().appendChild(g_kmlObject);

    // Walk the loaded KML object hierarchy looking for a <gx:Tour>.
    g_gex.dom.walk({
      rootObject: g_kmlObject,
      visitCallback: function(context) {
        if (this.getType() == 'KmlTour') {
          tourFound = true;
          g_ge.getTourPlayer().setTour(this);
          g_ge.getTourPlayer().play();
          return false;
        }
      }
    });

  } catch (ex) {
    alert('Error parsing KML!');
    return;
  }

  if (!tourFound) {
    aspectRatio = dojo.coords('right').w * 1.0 / dojo.coords('right').h;
    setTimeout('g_gex.util.flyToObject(g_kmlObject, { aspectRatio: 1 });',0)
  }
}

function dataUrlsSupported() {
  var userAgent = navigator.userAgent;

  if (userAgent.indexOf('Firefox/3') >= 0)
    return true;

  if (userAgent.indexOf('Safari') >= 0 &&
      (userAgent.indexOf('Version/3.2') >= 0 ||
       userAgent.indexOf('Version/4') >= 0))
    return true;

  return false;
}

function downloadKmlFile(kmlString) {
  if (!kmlString)
    kmlString = g_editor.getCode();

  if (!dataUrlsSupported()) {
    alert('Downloading the KML locally requires Firefox 3+ or Safari 3.2+');
    return;
  }

  var dataUrl = 'data:application/vnd.google-earth.kml+xml;base64,' +
      Base64.encode(kmlString);

  var oldDirty = g_editorDirty;
  g_editorDirty = false;
  window.location.href = dataUrl;
  g_editorDirty = oldDirty;
}

function toggleInfoBox() {
  g_infoBoxVisible = !g_infoBoxVisible;
  dojo.cookie('show-info-box', g_infoBoxVisible ? 'true' : 'false');
  if (!g_infoBoxVisible) {
    dojo.fx.wipeOut({ node: 'info-box', onEnd: function() {
      dojo.addClass('info-box-toggle', 'off');
      //dijit.byId('info-box').layout();
      dijit.byId('center').layout();
    } }).play();
  } else {
    dojo.fx.wipeIn({ node: 'info-box', onEnd: function() {
      dojo.removeClass('info-box-toggle', 'off');
      //dijit.byId('info-box').layout();
      dijit.byId('center').layout();
    } }).play();
  }
}

var interactiveSampler = {
  flyTo: function(lat, lng, options) {
    var la = g_ge.createLookAt('');
    la.setLatitude(lat);
    la.setLongitude(lng);

    if ('range' in options)
      la.setRange(options.range);

    if ('heading' in options)
      la.setHeading(options.heading);

    if ('tilt' in options)
      la.setTilt(options.tilt);

    g_ge.getView().setAbstractView(la);
  }

};

/* ]]> */
</script>
</head>
<body class="nihilo">
  <div id="loading"><span>Loading KML Interactive Sampler...</span></div>
  <div id="container" dojoType="dijit.layout.BorderContainer" region="center"
    style="visibility: hidden; height: 100%">

    <div id="top" dojoType="dijit.layout.ContentPane" region="top">
      <h1 style="margin:0; padding:0">KML Interactive Sampler</h1>
      <p style="margin:0; padding:0">Explore the samples below or enter your own KML to get started. You can then make changes and see them in action by clicking 'Update Earth'!<br/>
      <em>This sampler requires the <a href="https://developers.google.com/earth">Google Earth Plug-in</a></em>.</p>
    </div>

    <div id="left" dojoType="dijit.layout.ContentPane" region="left"
      splitter="true" minsize="200" style="width: 250px;">
      <script type="dojo/method" event="onResized">
        alert('hey');
      </script>

      <div dojoType="dojo.data.ItemFileReadStore" jsid="samplesStore"
        url="kml-samples.json"></div>

      <div id="tree" dojoType="AutoExpandRootTree"
        labelAttr="name"
        store="samplesStore"
        style="height: 100%;">
        <script type="dojo/method" event="onClick" args="item">
          if (item) {
            var source = samplesStore.getValue(item, 'source');
            var children = samplesStore.getValue(item, 'children');
            var descSource = samplesStore.getValue(item, 'descSource');

            if (source && !children)
              loadSample(source, descSource);

            document.location.hash = '#' + samplesStore.getIdentity(item);
          }
        </script>
        <script type="dojo/method" event="getLabelClass" args="item">
          if (item) {
            var children = samplesStore.getValue(item, 'children');
            if (!children)
              return 'leaf-label';
          }
        </script>
      </div>

    </div>

    <div id="center" dojoType="dijit.layout.BorderContainer" region="center">
      <div id="edit-toolbar" dojoType="dijit.layout.ContentPane" region="top">
        <div id="info-box" dojoType="dijit.layout.ContentPane">
          <div id="useful-links" dojoType="dijit.layout.ContentPane">
            <h3>Useful links</h3>
            <div></div>
          </div>
          <div id="sample-instructions" dojoType="dijit.layout.ContentPane">
            <p style="font-style: italic; font-weight: bold; color: #00aa00;">Instructions and useful links will appear here if available.</p>
          </div>
          <div style="clear: both; position: relative;"></div>
        </div>
        <button id="update-button" dojoType="dijit.form.Button" onclick="reloadKml();" title="Ctrl+S"><span>Update Earth</span></button>
        <button id="download-button" dojoType="dijit.form.Button" onclick="downloadKmlFile();"><span>Download</span></button>
        <a id="info-box-toggle" href="#" title="Toggle Info" onclick="toggleInfoBox(); return false;"></a>
      </div>
      <div dojoType="dijit.layout.ContentPane" region="center" id="editor-container">
<div id="editor-loading" style="width: 100%; height: 100%;">

</div>
<textarea id="editor" style="width: 100%; height: 100%">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;kml xmlns="http://www.opengis.net/kml/2.2"
     xmlns:gx="http://www.google.com/kml/ext/2.2"&gt;
  &lt;Document&gt;

  &lt;/Document&gt;
&lt;/kml&gt;
</textarea>
      </div>
    </div>

    <div id="right" dojoType="dijit.layout.ContentPane" region="right"
      splitter="true" sizerWidth="10" minsize="250" style="width: 400px;">
      <div id="map3d" style="height: 100%"></div>
    </div>

    <div id="bottom" dojoType="dijit.layout.ContentPane" region="bottom">
      More samples available at the <a href="https://code.google.com/p/kml-samples/source/browse/#svn/trunk">kml-samples</a> project.
    </div>

  </div>

</body>
</html>
